﻿using CorpStore.Common;
using CorpStore.Controls;
using CorpStore.Models;
using StoreHelper;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.ApplicationSettings;
using Windows.UI.Popups;
using Windows.UI.StartScreen;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227

namespace CorpStore
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        // Globals
        private static Log log = new Log();
        public static string STORE_FAMILY_NAME = "CorpStore_zykmbad61hv5m";
        public static string StoreTitle = "App Store";
        public static string PrivacyContact = "unknown";

        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspendingAsync;

            // set up handler for when bindings fail and for global unhandled exceptions
            this.DebugSettings.BindingFailed += DebugSettings_BindingFailed;
            this.UnhandledException += App_UnhandledException;
        }


        // handler for global unhandled exceptions - just show a message box
        async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            var dialog = new MessageDialog(e.Exception.Message + " " + e.Exception.StackTrace);
            await dialog.ShowAsync();
        }


        private void DebugSettings_BindingFailed(object sender, BindingFailedEventArgs e)
        {
            // set a breakpoint here to stop execution whenever there is a XAML binding failure
            string message = e.Message;
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected async override void OnLaunched(LaunchActivatedEventArgs e)
        {
            // initialize our logger
            await log.initAsync("Log\\CorpStore.log", true);

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                //Associate the frame with a SuspensionManager key                                
                SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

                // Set the default language
                rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

                rootFrame.NavigationFailed += OnNavigationFailed;

                // jump immediately to app details page if we were passed a package family name (this happens when user clicks on secondary tile)
                LogInfo("Arguments passed to OnLaunched = '{0}'", e.Arguments);
                string[] tokens = e.Arguments.Split(' ');
                if (tokens.Length > 0 && tokens[0] != "")
                {
                    string familyName = tokens[0];
                    NavData navData = new NavData() { FamilyName = familyName };
                    var serData = navData.Serialize();
                    if (!rootFrame.Navigate(typeof(AppDetailsPage), serData))
                    {
                        throw new Exception("Failed to Navigate to app details page");
                    }
                }

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    // we were previously terminated - try to restore our previous state
                    try
                    {
                        await SuspensionManager.RestoreAsync();
                    }
                    catch (SuspensionManagerException)
                    {
                        //Something went wrong restoring state.
                        //Assume there is no state and continue
                    }
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }
            else
                LogInfo("Rootframe was not null");

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                LogInfo("About to navigate to MainPage");
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();

            // set up our settings pane
            SettingsPane.GetForCurrentView().CommandsRequested += App_CommandsRequested;
        }


        void App_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
        {
            var aboutCmd = new SettingsCommand("about", "About", (handler) =>
            {
                var aboutControl = new AboutFlyout();
                aboutControl.Show();
            });

            var privacyCmd = new SettingsCommand("privacy", "Privacy", (handler) =>
            {
                var privacyControl = new PrivacyFlyout();
                privacyControl.Show();
            });

            args.Request.ApplicationCommands.Add(aboutCmd);
            args.Request.ApplicationCommands.Add(privacyCmd);
        }


        /// <summary>
        /// Invoked when Navigation to a certain page fails
        /// </summary>
        /// <param name="sender">The Frame which failed navigation</param>
        /// <param name="e">Details about the navigation failure</param>
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private async void OnSuspendingAsync(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            await SuspensionManager.SaveAsync();
            deferral.Complete();
        }


        // global logger routines
        public static void LogInfo(string msg, params object[] parms)
        {
            if (log != null)
                log.logInfo(msg, parms);
        }


        public static Task LogInfoWithMsg(string msg, params object[] parms)
        {
            if (log != null)
            {
                log.logInfo(msg, parms);
                return (GenLib.ShowMessageAsync(string.Format(msg, parms)));
            }
            else
                return null;
        }

        public static void LogInfoWithToast(string msg, params object[] parms)
        {
            if (log != null)
            {
                log.logInfo(msg, parms);
                GenLib.ShowToast(string.Format(msg, parms));
            }
        }

        public static void LogErr(string msg, params object[] parms)
        {
            if (log != null)
                log.logErr(msg, parms);
        }

        public static void LogErrWithMsg(string msg, params object[] parms)
        {
            if (log != null)
            {
                log.logErr(msg, parms);
                GenLib.ShowMessageAsync(string.Format(msg, parms));
            }
        }

    }
}
